/*
* Copyright (c) 2007 by Kirill Kolodyazhniy.
* See the file "license.terms" for information on usage and redistribution.
*/

#ifndef M_SLOTMESSAGE_H
#define M_SLOTMESSAGE_H

#include "refptr.h"

namespace Engine
{
	template<class T>
	struct ParamTraits
	{
		typedef T Type;
	};

	template<class T>
	struct ParamTraits<const T>
	{
		typedef T Type;
	};

	template<class T>
	struct ParamTraits<T&>
	{
		typedef T Type;
	};

	template<class T>
	struct ParamTraits<const T&>
	{
		typedef T Type;
	};

	/**
	*   Base class for messages.
	*/
	class SlotMessageBase
	{
	public:
		/**
		*   Virtual destructor.
		*/
		virtual ~SlotMessageBase(){}

		/**
		*   Run callback.
		*/
		void Fire(){ FireImpl();}

	protected:

		/**
		*   Implementation of callback running.
		*   Need to be override in derived classes.
		*/
		virtual void FireImpl() = 0;
	};

	/**
	*   Message implementation.
	*/
	template<class S>
	class SlotMessage0:public SlotMessageBase,public S
	{
	public:
		~SlotMessage0(){}
		SlotMessage0()
		{
		}

	private:
		void FireImpl()
		{
			S::Execute();
		}
	};

	/**
	*   Message implementation.
	*/
	template<class S,class Arg0>
	class SlotMessage1:public SlotMessageBase,public S
	{
	public:
		~SlotMessage1(){}
		SlotMessage1(Arg0 arg0):m_arg0(arg0)
		{
		}

	private:
		void FireImpl()
		{
			Execute(m_arg0);
		}

		typename ParamTraits<Arg0>::Type m_arg0;
	};
	/**
	*   Message implementation.
	*/
	template<class S,class Arg0,class Arg1>
	class SlotMessage2:public SlotMessageBase,public S
	{
	public:
		~SlotMessage2(){}
		SlotMessage2(Arg0 arg0,Arg1 arg1):m_arg0(arg0),m_arg1(arg1)
		{
		}

	private:
		void FireImpl()
		{
			Execute(m_arg0,m_arg1);
		}

		typename ParamTraits<Arg0>::Type m_arg0;
		typename ParamTraits<Arg1>::Type m_arg1;
	};

	/**
	*   Message implementation.
	*/
	template<class S,class Arg0,class Arg1,class Arg2>
	class SlotMessage3:public SlotMessageBase,public S
	{
	public:
		~SlotMessage3(){}
		SlotMessage3(Arg0 arg0,Arg1 arg1,Arg2 arg2):m_arg0(arg0),m_arg1(arg1),m_arg2(arg2)
		{
		}

	private:
		void FireImpl()
		{
			Execute(m_arg0,m_arg1,m_arg2);
		}

		typename ParamTraits<Arg0>::Type m_arg0;
		typename ParamTraits<Arg1>::Type m_arg1;
		typename ParamTraits<Arg2>::Type m_arg2;
	};

	/**
	*   Message implementation.
	*/
	template<class S,class Arg0,class Arg1,class Arg2,class Arg3>
	class SlotMessage4:public SlotMessageBase,public S
	{
	public:
		~SlotMessage4(){}
		SlotMessage4(Arg0 arg0,Arg1 arg1,Arg2 arg2,Arg3 arg3):m_arg0(arg0),m_arg1(arg1),m_arg2(arg2),m_arg3(arg3)
		{
		}

	private:
		void FireImpl()
		{
			Execute(m_arg0,m_arg1,m_arg2,m_arg3);
		}

		typename ParamTraits<Arg0>::Type m_arg0;
		typename ParamTraits<Arg1>::Type m_arg1;
		typename ParamTraits<Arg2>::Type m_arg2;
		typename ParamTraits<Arg3>::Type m_arg3;
	};

	/**
	*   Message implementation.
	*/
	template<class S,class Arg0,class Arg1,class Arg2,class Arg3,class Arg4>
	class SlotMessage5:public SlotMessageBase,public S
	{
	public:
		~SlotMessage5(){}
		SlotMessage5(Arg0 arg0,Arg1 arg1,Arg2 arg2,Arg3 arg3,Arg4 arg4):m_arg0(arg0),m_arg1(arg1),m_arg2(arg2),m_arg3(arg3),m_arg4(arg4)
		{
		}

	private:
		void FireImpl()
		{
			Execute(m_arg0,m_arg1,m_arg2,m_arg3,m_arg4);
		}

		typename ParamTraits<Arg0>::Type m_arg0;
		typename ParamTraits<Arg1>::Type m_arg1;
		typename ParamTraits<Arg2>::Type m_arg2;
		typename ParamTraits<Arg3>::Type m_arg3;
		typename ParamTraits<Arg4>::Type m_arg4;
	};

	/**
	*   Message implementation.
	*/
	template<class S,class Arg0,class Arg1,class Arg2,class Arg3,class Arg4,class Arg5>
	class SlotMessage6:public SlotMessageBase,public S
	{
	public:
		~SlotMessage6(){}
		SlotMessage6(Arg0 arg0,Arg1 arg1,Arg2 arg2,Arg3 arg3,Arg4 arg4,Arg5 arg5):m_arg0(arg0),m_arg1(arg1),m_arg2(arg2),m_arg3(arg3),m_arg4(arg4),m_arg5(arg5)
		{
		}

	private:
		void FireImpl()
		{
			Execute(m_arg0,m_arg1,m_arg2,m_arg3,m_arg4,m_arg5);
		}

		typename ParamTraits<Arg0>::Type m_arg0;
		typename ParamTraits<Arg1>::Type m_arg1;
		typename ParamTraits<Arg2>::Type m_arg2;
		typename ParamTraits<Arg3>::Type m_arg3;
		typename ParamTraits<Arg4>::Type m_arg4;
		typename ParamTraits<Arg5>::Type m_arg5;
	};

	/**
	*   Message implementation.
	*/
	template<class S,class Arg0,class Arg1,class Arg2,class Arg3,class Arg4,class Arg5,class Arg6>
	class SlotMessage7:public SlotMessageBase,public S
	{
	public:
		~SlotMessage7(){}
		SlotMessage7(Arg0 arg0,Arg1 arg1,Arg2 arg2,Arg3 arg3,Arg4 arg4,Arg5 arg5,Arg6 arg6):
			m_arg0(arg0),m_arg1(arg1),m_arg2(arg2),m_arg3(arg3),m_arg4(arg4),m_arg5(arg5),m_arg6(arg6)
		{			
		}

	private:
		void FireImpl()
		{
			Execute(m_arg0,m_arg1,m_arg2,m_arg3,m_arg4,m_arg5,m_arg6);
		}

		typename ParamTraits<Arg0>::Type m_arg0;
		typename ParamTraits<Arg1>::Type m_arg1;
		typename ParamTraits<Arg2>::Type m_arg2;
		typename ParamTraits<Arg3>::Type m_arg3;
		typename ParamTraits<Arg4>::Type m_arg4;
		typename ParamTraits<Arg5>::Type m_arg5;
		typename ParamTraits<Arg6>::Type m_arg6;		
	};


	/**
	*   Message implementation.
	*/
	template<class S,class Arg0,class Arg1,class Arg2,class Arg3,class Arg4,class Arg5,class Arg6,class Arg7>
	class SlotMessage8:public SlotMessageBase,public S
	{
	public:
		~SlotMessage8(){}
		SlotMessage8(Arg0 arg0,Arg1 arg1,Arg2 arg2,Arg3 arg3,Arg4 arg4,Arg5 arg5,Arg6 arg6,Arg7 arg7):
			m_arg0(arg0),m_arg1(arg1),m_arg2(arg2),m_arg3(arg3),m_arg4(arg4),m_arg5(arg5),m_arg6(arg6),m_arg7(arg7)
		{
		}

	private:
		void FireImpl()
		{
			Execute(m_arg0,m_arg1,m_arg2,m_arg3,m_arg4,m_arg5,m_arg6,m_arg7);
		}

		typename ParamTraits<Arg0>::Type m_arg0;
		typename ParamTraits<Arg1>::Type m_arg1;
		typename ParamTraits<Arg2>::Type m_arg2;
		typename ParamTraits<Arg3>::Type m_arg3;
		typename ParamTraits<Arg4>::Type m_arg4;
		typename ParamTraits<Arg5>::Type m_arg5;
		typename ParamTraits<Arg6>::Type m_arg6;
		typename ParamTraits<Arg7>::Type m_arg7;
	};
}

#endif

